package one_many

import (
	"producter_consumer/out"
	"sync"
)

//  一个生产者对应多个消费者的情况

type Task struct {
	ID int64
}

// 运行
func (t *Task) run() {
	out.Println(t.ID)
}

// 定义channel,并给一个缓存为 10
var taskCh = make(chan Task, 10)

const taskNum int64 = 10000

// 生产者,只做写入操作,不做读取 这里一对多的情况下,生产者不变
func producer(wo chan<- Task) {
	// 给 channel 写入数据
	var i int64
	for i = 1; i < taskNum; i++ {
		t := Task{
			ID: i,
		}
		wo <- t
	}
	// 因为只有一个生产者,所以生产以后就可以直接关闭通道
	close(wo)
}

// 定义一个消费者-这里多个消费者的情况下
func consumer(ro <-chan Task) {
	// 遍历, 这里在多个协程一起运行的情况下,有100个协程同时访问一个值
	for t := range ro {
		if t.ID != 0 {
			t.run()
		}
	}
}

// Exec 新建两个协程调用
func Exec() {
	// 生产者
	go producer(taskCh)
	// 消费者
	go consumer(taskCh)
}

// ExecWg 下面使用 waitgroup 来处理
func ExecWg() {
	wg := sync.WaitGroup{}
	wg.Add(1) // 这里添加协程的数量 - 生产者1个
	// 生产者
	go func() {
		defer wg.Done()
		producer(taskCh)
	}()

	// 消费者 - 一个消费者的情况
	//go func() {
	//	defer wg.Done()
	//	consumer(taskCh)
	//}()

	// 这里消费者的wg数量也需要变更

	// 这里是多个消费者的情况下,需要循环遍历多个消费者的情况
	var i int64
	for i = 0; i < taskNum; i++ {
		if i%100 == 0 {
			wg.Add(1) // 每次起一个协程,计数器就需要加1
			go func() {
				defer wg.Done()
				consumer(taskCh)
			}()
		}
	}

	// 这里在两个协程执行完成以后就结束wait
	wg.Wait()
	out.Println("执行成功")
}
